package com.edu.juc.interrupt.lockSupport;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.LockSupport;
import java.util.concurrent.locks.ReentrantLock;

/**
 * LockSupport 用于创建锁和其他同步类的基本线程阻塞原语。
 * <p>
 * 阻塞唤醒线程的三种方式：
 * 1. Object: wait/notify
 * 2. Condition: await/signal
 * Object和Condition
 * 限制：
 * -- 线程先要获得并持有锁，必须在锁块(synchronized/lock)中
 * -- 只能唤醒等待中的线程
 * 3. LockSupport: park/unpark
 * -- LockSupport类使用了一种名为Permit许可的概念来做到阻塞和唤醒线程的功能，每个线程都有一个许可Permit
 * -- 但与Semaphore不同的是，许可的累加上限是 1。
 */
public class LockSupportTest {

    public static void main(String[] args) {

        ReentrantLock lock = new ReentrantLock();

        Thread thread1 = new Thread(() -> {
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
//            lock.lock();
            System.out.println("begin park");
            LockSupport.park();
            System.out.println("end park");
//            lock.unlock();
        }, "t1");
        thread1.start();

        Thread thread2 = new Thread(() -> {
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
//            lock.lock(); // park()不会释放锁
            System.out.println("begin park");
            LockSupport.park();
            System.out.println("end park");
//            lock.unlock();
        }, "t2");
        thread2.start();


        new Thread(() -> {
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            System.out.println("begin unpark");
            LockSupport.unpark(thread1);
            LockSupport.unpark(thread1); // 与Semaphore不同的是，许可的累加上限是 1。
            LockSupport.unpark(thread2);

            System.out.println("end unpark");
        }, "t2").start();
    }
}
